﻿using Spider.Framework.UtilityCommon;
using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;
using Spider.Framework.UtilityCommon.Extensions;
using MyCrawler.Entity;
using MyCrawler.Dals;
using MyCrawler.Utilyties;
using System.Threading;

namespace MyCrawler.Controls
{
    /// <summary>
    /// http://diendan.phununet.com/
    /// </summary>
    public class PhuNuNetForumCtr : ForumsCtr
    {
        public PhuNuNetForumCtr()
        {
            _source = "diendan.phununet.com";
            _linkInit = "http://diendan.phununet.com/";
            _domain = "http://diendan.phununet.com/"; // dùng cho các trang sub trở đi, vì sẽ nối trang với domain
            _blockId = DateTime.Now.ToString("yyyyMMddhhmmss");
            _pageLimit = -1;
        }

        /// <summary>
        /// Contructor thứ 2
        /// </summary>
        /// <param name="source">nguồn</param>
        /// <param name="linkInit">link khởi tạo</param>
        /// <param name="domain">domain gốc - có thể trùng với link khởi tạo</param>
        /// <param name="blockId">mỗi lần khởi tạo sẽ có 1 block id, chứa list các thread</param>
        public PhuNuNetForumCtr(string source, string linkInit, string domain, string blockId)
        {
            _source = source;
            _linkInit = linkInit;
            _domain = domain; // dùng cho các trang sub trở đi, vì sẽ nối trang với domain
            _blockId = blockId;

            _pageLimit = -1;
        }

        public override List<string> GetCatalogByLink()
        {
            try
            {
                string html = GetContentWithStream(_linkInit, -1);
                List<string> ls_L1 = UtilityCtr.GetListItem(html, @"<a[\s]+href='\/dspSingleCategory.aspx\?Pk_iCatID=[\d]+'[\s]+style='font-weight:[\s]+[\d]+;[\s]+color:[\s#\d\w]+'>Tất[\s]+cả[\s]+chủ[\s]+đề(.*?)<\/a>");

                List<string> lsLinkStored = new List<string>();
                for (int i = 0; i < ls_L1.Count; i++)
                {
                    string link_l1 = _domain + UtilityCtr.GetItemFirst(ls_L1[i], @"href='.*?'").Replace("href='/", "").Replace("'", "");
                    lsLinkStored.Add(link_l1);
                }
                return lsLinkStored;

            }
            catch { }

            return null;
        }

        public override void GetListTopic_InCatagory(string lnkCat)
        {
            try
            {
                TraceLog_Status(_source, _blockId, " + " + lnkCat);

                string s = GetContentWithStream(lnkCat, -1);

                if (s.IsStringNullOrEmpty())
                {
                    TraceLog_Status(_source, _blockId, " --- Data null Or empty. WebClient request time out. Kiểm tra Website có bị chết hay không hay kiểm tra kết nối internet của bạn! "); // ghi log để test
                    return;
                }

                // lấy các chủ đề ngày trang đầu
                GetTopicsInPage(s, 1);

                #region  lấy các chủ đề từ trang thứ 2 trờ đi - nếu có
                try
                {
                    List<string> lsPager = UtilityCtr.GetListItem(s, @"<a[\s]+href='\/dspSingleCategory.aspx\?Pk_iCatID=[\d]+&CategoryId=[\d]+&page=[\d]+'>[\d]+");
                    string pager = lsPager[lsPager.Count - 1].GetElement(@"[\d]+$", false, PatternType.Regex);
                    int tPage = Convert.ToInt32(pager);

                    _pageLimit = -1; // khởi tạo trang giới hạn
                    for (int j = 2; j <= tPage; j++) // duyêt từ trang số 2 trở đi
                    {
                        if (_pageLimit != -1 && j > _pageLimit) // đã tìm thấy trang giới hạn, trang này có ngày cập nhật nhỏ hơn ngày giới hạn
                        {
                            break;
                        }

                        string linkPager = lnkCat + "&page=" + j.ToString();
                        s = GetContentWithStream(linkPager, -1);

                        GetTopicsInPage(s, j); // lấy các chủ đề của trang 1
                    }
                }
                catch { }
                #endregion
            }
            catch (Exception ex)
            {
                TraceLog_Status(_source, _blockId, " --- Error: " + ex.Message);
            }
        }

        private void GetTopicsInPage(string contentHtml, int pageIndex)
        {
            try
            {
                var lisTopic = contentHtml.GetElements(@"<div[\s]+class='rowItem'[\s]+style='font-weight:[\s\d]+;'>.*?<\/td>", false, PatternType.Regex);

                if (lisTopic == null || lisTopic.Count == 0)
                {
                    TraceLog_Status(_source, _blockId, " --- không tìm thấy Topic, kiểm tra Catagorie này có thay đổi source code!"); // ghi log để test
                    return;
                }

                for (int i = 0; i < lisTopic.Count; i++)
                {
                    string strDate = lisTopic[i].GetElement(@"([\d]+\/[\d]+\/[\d]+[\s]+[\d]+:[\d]+[\s]+(AM|PM))", false, PatternType.Regex);

                    if (strDate.IsStringNullOrEmpty())
                    {
                        TraceLog_Status(_source, _blockId, " --- Ngày 'last reply' không tồn tại, có thể chủ đề đã bị xóa, đã di chuyển, hay website nguồn có sự thay đổi souce code!");
                        continue;
                    }

                    try
                    {
                        // 26/04-2014 09:03 PM
                        string[] arrDate = strDate.Split(' '); // dạng: 04-13-2014,12:00 am hoặc hôm nay, 12:00 pm

                        string day = "";

                        // format của nó là MM/dd/yyyy hh:mm tt => chuyển nó về yyyy-MM-dd hh:mm
                        if (arrDate.Length == 3)
                        {
                            string[] arrDay = arrDate[0].Split('/');
                            day = arrDay[2] + "-" + arrDay[1] + "-" + arrDay[0] + " " + arrDate[1] + ":" + DateTime.Now.ToString("ss.fff") + " " + arrDate[2];
                        }

                        DateTime dtLastDate = Convert.ToDateTime(day);

                        // kiểm tra ngày này có nhỏ hơn ngày giới hạn lấy hay không?
                        if (dtLastDate >= _dtLimit)// trong thời gian 30 ngày mà không có ai trả lời, không lấy dữ liệu mới về nữa
                        {
                            #region thực hiện lấy data
                            string lnk = UtilityCtr.GetItemFirst(lisTopic[i], @"href='\/dspSingleTopic.aspx\?TopicId=.*?'");
                            lnk = _domain + Regex.Replace(lnk, @"(href='\/)|(')", "");

                            if (lnk.IsStringNullOrEmpty() == true)
                            {
                                TraceLog_Status(_source, _blockId, " --- Link của topic rỗng, có thể website nguồn có sự thay đổi souce code!");
                                continue; // chạy tới topic kế mà không quan tâm đoạn dưới
                            }

                            string subj = UtilityCtr.GetItemFirst(lisTopic[i], @"<a.*?<\/a>");
                            subj = Regex.Replace(subj, @"<.*?>", "");

                            int id;
                            try
                            {
                                id = Convert.ToInt32(lnk.GetElement(@"=[\d]+&", false, PatternType.Regex).Replace("=", "").Replace("&", ""));
                            }
                            catch
                            {
                                id = 0;
                            }

                            #endregion

                            GetContent(lnk, subj, id, dtLastDate);
                        }
                        else
                        {
                            if (pageIndex > 1) // nếu đây là trang thứ 2 trở đi
                            {
                                _pageLimit = pageIndex; // đánh dấu trang hiện hành này là trang giới hạn, vì các chủ để từ trang sau luôn có ngày reply nhỏ hơn ngày giới hạn
                                break;
                            }
                        }
                    }
                    catch { }
                }
            }
            catch
            { }
        }

        public void GetContent(string lnk, string subj, long idTopic, DateTime lastModify)
        {
            try
            {
                TraceLog_Status(_source, _blockId, " --- " + lnk);// ghi log để test

                string html = GetContentWithStream(lnk, 250);

                if (html.IsStringNullOrEmpty())
                {
                    TraceLog_Status(_source, _blockId, " --- --- Data null Or empty. WebClient request time out. Kiểm tra Website có bị chết hay không hay kiểm tra kết nối internet của bạn! "); // ghi log để test
                    return;
                }

                #region lấy tên danh mục
                var catLis = html.GetElements(@"(<a id='_ctl0__ctl0_cphBodyContent_ContentPlaceHolder1_SingleTopic1_lblTenCategory).*?<\/a>", false, PatternType.Regex);
                string catName = "";
                if (catLis == null || catLis.Count == 0)
                {
                    TraceLog_Status(_source, _blockId, " --- --- Lấy tên danh mục trên thanh navigation rỗng, có thể website nguồn có sự thay đổi souce code!");
                }
                else
                {
                    catName = Regex.Replace(catLis[catLis.Count - 1], @"<.*?>", "").Trim();
                }
                #endregion

                var lisPos = html.GetElements(@"(<div[\s]+class='cl2'>[\s]{0,}<div[\s]+class='rw[\d]+'>)(.*?)(<div[\s]+class='rw3'.*?>)", false, PatternType.Regex);

                if (lisPos == null || lisPos.Count == 0)
                {
                    TraceLog_Status(_source, _blockId, " --- --- Bài viết và Bình luận = 0, có thể website nguồn có sự thay đổi souce code, hay ip bị block!");
                    return;
                }

                // lấy nội dung bài viết - mẩu tin đầu của trang đầu
                string cont = Regex.Replace(lisPos[0], @"<.*?>", " ").Replace("&nbsp;", " ");
                // replace nhiều khoảng trắng thành 1 khoảng trắng
                cont = Regex.Replace(cont, @"[\s]+", " ").Trim();

                #region [lấy bình luận]

                List<string> lsCmt = new List<string>();

                for (int i = 1; i < lisPos.Count; i++)
                {
                    string cmt = Regex.Replace(lisPos[i], @"<.*?>", " ").Replace("&nbsp;", " ");
                    // replace nhiều khoảng trắng thành 1 khoảng trắng
                    cmt = Regex.Replace(cmt, @"[\s]+", " ").Trim();
                    lsCmt.Add(cmt);
                }
                #endregion

                #region lấy bình luận từ trang 2 trở đi
                try
                {
                    List<string> lsPager = UtilityCtr.GetListItem(html, @"<a[\s]+href='\?TopicId=[\d]+&Pk_iCatId=[\d]+&page=[\d]+'>[\d]+");
                    string pager = UtilityCtr.GetItemFirst(lsPager[lsPager.Count - 1], @"[\d]+$");

                    int totalPage = Convert.ToInt32(pager);
                    for (int i = 2; i <= totalPage; i++) // duyêt từ trang số 2 trở đi
                    {
                        string lnkSub = lnk + "&page=" + i.ToString();
                        string htmlSub = GetContentWithStream(lnkSub, 250);

                        // lấy danh sách
                        var lisPosSub = UtilityCtr.GetListItem(htmlSub, @"<div[\s]+class='cl2'>[\s]{0,}<div[\s]+class='rw2'>.*?<div[\s]+class='rw3'.*?>");

                        for (int j = 0; j < lisPosSub.Count; j++)
                        {
                            string cmtsub = Regex.Replace(lisPosSub[j], @"<.*?>", " ").Replace("&nbsp;", " ");
                            // replace nhiều khoảng trắng thành 1 khoảng trắng
                            cmtsub = Regex.Replace(cmtsub, @"[\s]+", " ").Trim();

                            lsCmt.Add(cmtsub);
                        }
                    }
                }
                catch { }
                #endregion

                #region [Lưu lại]

                ContentEntity entity = new ContentEntity();

                entity.Category = catName;
                entity.Comments = lsCmt;
                entity.Content = cont;
                entity.Id = idTopic;
                entity.LastModify = lastModify;
                entity.Link = lnk;
                entity.Source = _source;
                entity.Summury = "";
                entity.Title = subj;

                // ghi log để review
                TraceLog_Status(_source, _blockId, " --- --- Comments: " + lsCmt.Count.ToString() + " -- Last modify: " + lastModify.ToString("yyyy-MM-dd hh:mm:ss tt"));
                // lưu vào file json
                string file = LogFileJson(entity);
                // ghi log để review
                TraceLog_Status(_source, _blockId, " --- --- File json: " + file);

                // tăng số topic lên 1 để thực hiện việc thống kê
                _totalTopic = _totalTopic + 1;
                UtilityCtr.TraceSettingTime(_source, _timeStart, _totalTopic, _dtLimit.ToString("yyyy-MM-dd hh:mm:ss tt"));
                #endregion
            }
            catch (Exception ex)
            {
                TraceLog_Status(_source, _blockId, lnk + " --- --- Error: " + ex.Message); // ghi log để test
            }
        }
    }
}
